"""
Grave! Important! Важно!

Proletoj el ĉiuj landoj, unuiĝu!
Workers of the world, unite!
Пролетарии всех стран, соединяйтесь!

https://tkom.pro
"""

import sys
from django.db import models
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.models import Permission
from django.db.models import Max, Q

from siriuso.models.postgres import CallableEncoder
from siriuso.utils import default_lingvo, get_enhavo, perms
from main.models import Uzanto
from komunumoj.models import Komunumo
from universo_bazo.models import UniversoBazaMaks, UniversoBazaRealeco, Realeco
from organizoj.models import Organizo
from laborspacoj.models import Klastero

# Категории холстов, использует абстрактный класс UniversoBazaMaks
class KanvasoKategorio(UniversoBazaMaks):

    # ID записи для вывода
    id = models.IntegerField(_('ID'), unique=True, default=0)

    # автор (пользователь, который создал сущность)
    autoro = models.ForeignKey(Uzanto, verbose_name=_('Aŭtoro'), blank=False, default=None,
                               related_name='%(app_label)s_%(class)s_autoro',
                               on_delete=models.CASCADE)

    # название, многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # параллельный мир в котором есть эта сущность, может быть в нескольких
    realeco = models.ManyToManyField(Realeco, verbose_name=_('Realeco'),
                                     db_table='kanvasoj_kanvaso_kategorioj_realeco_ligiloj')

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'kanvasoj_kanvaso_kategorioj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Kategorio de kanvaso de kanvasoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Kategorioj de kanvaso de kanvasoj')
        # права
        permissions = (
            ('povas_vidi_kanvasoj_kanvaso_kategorioj', _('Povas vidi kategorioj de kanvaso de kanvasoj')),
            ('povas_krei_kanvasoj_kanvaso_kategorioj', _('Povas krei kategorioj de kanvaso de kanvasoj')),
            ('povas_forigi_kanvasoj_kanvaso_kategorioj', _('Povas forigi kategorioj de kanvaso de kanvasoj')),
            ('povas_shangxi_kanvasoj_kanvaso_kategorioj', _('Povas ŝanĝi kategorioj de kanvaso de kanvasoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}) {}'.format(self.id, get_enhavo(self.nomo, empty_values=True)[0])

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):
        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.all().aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id += 1
            super(model, self).__setattr__('id', next_id)

        super(KanvasoKategorio, self).save(force_insert=force_insert, force_update=force_update,
                                              using=using, update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистрированных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('kanvasoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'kanvasoj.povas_vidi_kanvasoj_kanvaso_kategorioj',
                'kanvasoj.povas_krei_kanvasoj_kanvaso_kategorioj',
                'kanvasoj.povas_forigi_kanvasoj_kanvaso_kategorioj',
                'kanvasoj.povas_shangxi_kanvasoj_kanvaso_kategorioj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='kanvasoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_kategorioj')
                    or user_obj.has_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_kategorioj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_kategorioj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Типы холстов, использует абстрактный класс UniversoBazaMaks
class KanvasoTipo(UniversoBazaMaks):

    # ID записи для вывода
    id = models.IntegerField(_('ID'), unique=True, default=0)

    # автор (пользователь, который создал сущность)
    autoro = models.ForeignKey(Uzanto, verbose_name=_('Aŭtoro'), blank=False, default=None,
                               related_name='%(app_label)s_%(class)s_autoro',
                               on_delete=models.CASCADE)

    # название, многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # параллельный мир в котором есть эта сущность, может быть в нескольких
    realeco = models.ManyToManyField(Realeco, verbose_name=_('Realeco'),
                                     db_table='kanvasoj_kanvaso_tipoj_realeco_ligiloj')

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'kanvasoj_kanvaso_tipoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Tipo de kanvaso de kanvasoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Tipoj de kanvaso de kanvasoj')
        # права
        permissions = (
            ('povas_vidi_kanvasoj_kanvaso_tipoj', _('Povas vidi tipoj de kanvaso de kanvasoj')),
            ('povas_krei_kanvasoj_kanvaso_tipoj', _('Povas krei tipoj de kanvaso de kanvasoj')),
            ('povas_forigi_kanvasoj_kanvaso_tipoj', _('Povas forigi tipoj de kanvaso de kanvasoj')),
            ('povas_shangxi_kanvasoj_kanvaso_tipoj', _('Povas ŝanĝi tipoj de kanvaso de kanvasoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}) {}'.format(self.id, get_enhavo(self.nomo, empty_values=True)[0])

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):
        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.all().aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id += 1
            super(model, self).__setattr__('id', next_id)

        super(KanvasoTipo, self).save(force_insert=force_insert, force_update=force_update,
                                               using=using, update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистрированных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('kanvasoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'kanvasoj.povas_vidi_kanvasoj_kanvaso_tipoj',
                'kanvasoj.povas_krei_kanvasoj_kanvaso_tipoj',
                'kanvasoj.povas_forigi_kanvasoj_kanvaso_tipoj',
                'kanvasoj.povas_shangxi_kanvasoj_kanvaso_tipoj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='kanvasoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_tipoj')
                    or user_obj.has_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_tipoj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_tipoj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Статус холстов, использует абстрактный класс UniversoBazaMaks
class KanvasoStatuso(UniversoBazaMaks):

    # уникальный личный ID
    id = models.IntegerField(_('ID'), unique=True, default=0)

    # автор (пользователь, который создал сущность)
    autoro = models.ForeignKey(Uzanto, verbose_name=_('Aŭtoro'), blank=False, default=None,
                               related_name='%(app_label)s_%(class)s_autoro',
                               on_delete=models.CASCADE)

    # название, многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'kanvasoj_kanvaso_statusoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Statuso de kanvaso de kanvasoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Statusoj de kanvaso de kanvasoj')
        # права
        permissions = (
            ('povas_vidi_kanvasoj_kanvaso_statusoj', _('Povas vidi statusoj de kanvaso de kanvasoj')),
            ('povas_krei_kanvasoj_kanvaso_statusoj', _('Povas krei statusoj de kanvaso de kanvasoj')),
            ('povas_forigi_kanvasoj_kanvaso_statusoj', _('Povas forigi statusoj de kanvaso de kanvasoj')),
            ('povas_shangxi_kanvasoj_kanvaso_statusoj', _('Povas ŝanĝi statusoj de kanvaso de kanvasoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}) {}'.format(self.id, get_enhavo(self.nomo, empty_values=True)[0])

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):

        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.all().aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id = next_id + 1
            super(model, self).__setattr__('id', next_id)

        super(KanvasoStatuso, self).save(force_insert=force_insert, force_update=force_update,
                                            using=using, update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистрированных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('kanvasoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'kanvasoj.povas_vidi_kanvasoj_kanvaso_statusoj',
                'kanvasoj.povas_krei_kanvasoj_kanvaso_statusoj',
                'kanvasoj.povas_forigi_kanvasoj_kanvaso_statusoj',
                'kanvasoj.povas_shangxi_kanvasoj_kanvaso_statusoj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='kanvasoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_statusoj')
                    or user_obj.has_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_statusoj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_statusoj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Модель связи Холстов с Кластерами Многие-ко-Многим с дополнительными полями
class KanvasoKlasteroLigilo(models.Model):
    kanvaso = models.ForeignKey('Kanvaso', verbose_name=_('Kanvaso'), blank=False,
                                related_name='%(app_label)s_%(class)s_kanvaso',
                                default=None,
                                on_delete=models.CASCADE)

    klastero = models.ForeignKey(Klastero, verbose_name=_('Laborspacoj klastero'), blank=False, default=None,
                                 related_name='%(app_label)s_%(class)s_klastero',
                                 on_delete=models.CASCADE)

    # позиция в списке
    pozicio = models.IntegerField(_('Pozicio'), blank=True, null=True, default=None)

    # название, многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'kanvasoj_kanvaso_klastero_ligilo'
        # читабельное название модели, в единственном числе
        verbose_name = _('Kanvaso klastero ligilo')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Kanvasoj klasteroj ligiloj')
        unique_together = ("kanvaso", "klastero")


# Холсты, использует абстрактный класс UniversoBazaRealeco
class Kanvaso(UniversoBazaRealeco):

    # уникальный личный ID
    id = models.IntegerField(_('ID'), unique=True, default=0)
    
    # категория холста
    kategorio = models.ManyToManyField(KanvasoKategorio, verbose_name=_('Kategorio'),
                                       blank=True, 
                                       db_table='kanvasoj_kanvaso_kategorioj_ligiloj')

    # тип холста
    tipo = models.ForeignKey(KanvasoTipo, verbose_name=_('Tipo'), blank=True, default=None, null=True,
                             related_name='%(app_label)s_%(class)s_tipo',
                             on_delete=models.CASCADE)

    # статус холста
    statuso = models.ForeignKey(KanvasoStatuso, verbose_name=_('Statuso'), blank=True, default=None, null=True,
                                related_name='%(app_label)s_%(class)s_statuso',
                                on_delete=models.CASCADE)

    # позиция в списке
    pozicio = models.IntegerField(_('Pozicio'), blank=True, null=True, default=None)

    # название, многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)
    
    # кластер
    klasteroj = models.ManyToManyField(Klastero,
                                     through='KanvasoKlasteroLigilo',
                                     related_name='%(app_label)s_%(class)s_klasteroj',
                                     verbose_name=_('Klastero'), blank=True)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'kanvasoj_kanvaso'
        # читабельное название модели, в единственном числе
        verbose_name = _('Kanvasoj de kanvaso')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Kanvasoj de kanvasoj')
        # права
        permissions = (
            ('povas_vidi_kanvasoj_kanvaso', _('Povas vidi kanvaso de kanvasoj')),
            ('povas_krei_kanvasoj_kanvaso', _('Povas krei kanvaso de kanvasoj')),
            ('povas_forigi_kanvasoj_kanvaso', _('Povas forigi kanvaso de kanvasoj')),
            ('povas_shangxi_kanvasoj_kanvaso', _('Povas ŝanĝi kanvaso de kanvasoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}, id={}'.format(get_enhavo(self.nomo, empty_values=True)[0], self.id)

    # реализация автоинкрементов при сохранении
    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):

        # реализация автоинкремента шаблона при сохранении
        if self.sxablono_sistema:
            if self.sxablono_sistema_id is None or not self.sxablono_sistema_id:
                model = getattr(sys.modules[self.__module__], self.__class__.__name__)
                next_id = model.objects.all().aggregate(Max('sxablono_sistema_id'))['sxablono_sistema_id__max']

                if next_id is None:
                    next_id = 1
                else:
                    next_id = next_id + 1
                super(model, self).__setattr__('sxablono_sistema_id', next_id)

        # реализация автоинкремента при сохранении
        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.all().aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id = next_id + 1
            super(model, self).__setattr__('id', next_id)

        super(Kanvaso, self).save(force_insert=force_insert, force_update=force_update,
                                     using=using, update_fields=update_fields)


    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            if user_obj.is_superuser:
                all_perms = Permission.objects.filter(content_type__app_label='kanvasoj')
            else:
                # выбрать права, какие относятся к моделе
                model_perms = set([
                    'povas_vidi_kanvasoj_kanvaso',
                    'povas_krei_kanvasoj_kanvaso',
                    'povas_forigi_kanvasoj_kanvaso',
                    'povas_shangxi_kanvasoj_kanvaso'
                ])
                # выбираем права, какие есть у пользователя по данной моделе
                all_perms = set(user_obj.user_permissions.filter(
                    content_type__app_label='kanvasoj', codename__in=model_perms).values_list('codename', flat=True))
                # ЗДЕСЬ начинается блок добавления прав согласно условиям пользователя !!!
                # владелец пространства имеет все права
                count_posedantoj = KanvasoPosedanto.objects.filter(kanvaso=self, posedanto_uzanto=user_obj).count()
                if count_posedantoj:
                    all_perms = all_perms.union({
                        'povas_vidi_kanvasoj_kanvaso',
                        'povas_krei_kanvasoj_kanvaso',
                        'povas_forigi_kanvasoj_kanvaso',
                        'povas_shangxi_kanvasoj_kanvaso',
                        'povas_vidi_kanvasoj_kanvaso_posedantoj',
                        'povas_krei_kanvasoj_kanvaso_posedantoj', # имеет право создавать владельцев
                        'povas_krei_kanvasoj_kanvaso_objekto', # может создавать объекты холста по своему холсту
                    })

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='kanvasoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso')
                    or user_obj.has_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если член организации-владельца (клиента), то выдаём по нему данные
                cond = Q(kanvasoj_kanvasoposedanto_kanvaso__posedanto_uzanto__id=user_obj.id) | Q(
                    kanvasoj_kanvasoposedanto_kanvaso__posedanto_organizo__organizomembro__uzanto__id=user_obj.id) | Q(
                    kanvasoj_kanvasoposedanto_kanvaso__posedanto_komunumo__komunumoj_komunumomembro_posedanto__autoro__id=user_obj.id)
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                # cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Типы владельцев холстов, использует абстрактный класс UniversoBazaMaks
class KanvasoPosedantoTipo(UniversoBazaMaks):

    # уникальный личный ID
    id = models.IntegerField(_('ID'), unique=True, default=0)

    # автор (пользователь, который создал сущность)
    autoro = models.ForeignKey(Uzanto, verbose_name=_('Aŭtoro'), blank=False, default=None,
                               related_name='%(app_label)s_%(class)s_autoro',
                               on_delete=models.CASCADE)

    # название, многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'kanvasoj_kanvaso_posedantoj_tipoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Tipo de posedantoj de kanvaso de kanvasoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Tipoj de posedantoj de kanvaso de kanvasoj')
        # права
        permissions = (
            ('povas_vidi_kanvasoj_kanvaso_posedantoj_tipoj',
             _('Povas vidi tipoj de posedantoj de kanvaso de kanvasoj')),
            ('povas_krei_kanvasoj_kanvaso_posedantoj_tipoj',
             _('Povas krei tipoj de posedantoj de kanvaso de kanvasoj')),
            ('povas_forigi_kanvasoj_kanvaso_posedantoj_tipoj',
             _('Povas forigi tipoj de posedantoj de kanvaso de kanvasoj')),
            ('povas_shangxi_kanvasoj_kanvaso_posedantoj_tipoj',
             _('Povas ŝanĝi tipoj de posedantoj de kanvaso de kanvasoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}) {}'.format(self.id, get_enhavo(self.nomo, empty_values=True)[0])

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):

        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.all().aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id = next_id + 1
            super(model, self).__setattr__('id', next_id)

        super(KanvasoPosedantoTipo, self).save(force_insert=force_insert, force_update=force_update,
                                                        using=using, update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистрированных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('kanvasoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'kanvasoj.povas_vidi_kanvasoj_kanvaso_posedantoj_tipoj',
                'kanvasoj.povas_krei_kanvasoj_kanvaso_posedantoj_tipoj',
                'kanvasoj.povas_forigi_kanvasoj_kanvaso_posedantoj_tipoj',
                'kanvasoj.povas_shangxi_kanvasoj_kanvaso_posedantoj_tipoj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='kanvasoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_posedantoj_tipoj')
                    or user_obj.has_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_posedantoj_tipoj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_posedantoj_tipoj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Статус владельца холста, использует абстрактный класс UniversoBazaMaks
class KanvasoPosedantoStatuso(UniversoBazaMaks):

    # уникальный личный ID
    id = models.IntegerField(_('ID'), unique=True, default=0)

    # автор (пользователь, который создал сущность)
    autoro = models.ForeignKey(Uzanto, verbose_name=_('Aŭtoro'), blank=False, default=None,
                               related_name='%(app_label)s_%(class)s_autoro',
                               on_delete=models.CASCADE)

    # название, многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'kanvasoj_kanvaso_posedantoj_statusoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Statuso de posedantoj de kanvaso de kanvasoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Statusoj de posedantoj de kanvaso de kanvasoj')
        # права
        permissions = (
            ('povas_vidi_kanvasoj_kanvaso_posedantoj_statusoj',
             _('Povas vidi statusoj de posedantoj de kanvaso de kanvasoj')),
            ('povas_krei_kanvasoj_kanvaso_posedantoj_statusoj',
             _('Povas krei statusoj de posedantoj de kanvaso de kanvasoj')),
            ('povas_forigi_kanvasoj_kanvaso_posedantoj_statusoj',
             _('Povas forigi statusoj de posedantoj de kanvaso de kanvasoj')),
            ('povas_shangxi_kanvasoj_kanvaso_posedantoj_statusoj',
             _('Povas ŝanĝi statusoj de posedantoj de kanvaso de kanvasoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}) {}'.format(self.id, get_enhavo(self.nomo, empty_values=True)[0])

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):

        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.all().aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id = next_id + 1
            super(model, self).__setattr__('id', next_id)

        super(KanvasoPosedantoStatuso, self).save(force_insert=force_insert, force_update=force_update,
                                                     using=using, update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистрированных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('kanvasoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'kanvasoj.povas_vidi_kanvasoj_kanvaso_posedantoj_statusoj',
                'kanvasoj.povas_krei_kanvasoj_kanvaso_posedantoj_statusoj',
                'kanvasoj.povas_forigi_kanvasoj_kanvaso_posedantoj_statusoj',
                'kanvasoj.povas_shangxi_kanvasoj_kanvaso_posedantoj_statusoj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='kanvasoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_posedantoj_statusoj')
                    or user_obj.has_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_posedantoj_statusoj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_posedantoj_statusoj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Владельцы холстов, использует абстрактный класс UniversoBazaRealeco
class KanvasoPosedanto(UniversoBazaRealeco):

    # холст
    kanvaso = models.ForeignKey(Kanvaso, verbose_name=_('Kanvaso'), blank=False, null=False,
                              related_name='%(app_label)s_%(class)s_kanvaso',
                              default=None, on_delete=models.CASCADE)

    # пользователь владелец холста
    posedanto_uzanto = models.ForeignKey(Uzanto, verbose_name=_('Posedanta uzanto'), blank=True, null=True,
                                         related_name='%(app_label)s_%(class)s_posedanto_uzanto',
                                         default=None, on_delete=models.CASCADE)

    # организация владелец холста
    posedanto_organizo = models.ForeignKey(Organizo, verbose_name=_('Posedanta organizo'), blank=True,
                                           related_name='%(app_label)s_%(class)s_posedanto_organizo',
                                           null=True, default=None, on_delete=models.CASCADE)

    # сообщество владелец холста
    posedanto_komunumo = models.ForeignKey(Komunumo, verbose_name=_('Posedanta komunumo'), blank=True,
                                           related_name='%(app_label)s_%(class)s_posedanto_komunumo',
                                           default=None, null=True, on_delete=models.CASCADE)

    # тип владельца холста
    tipo = models.ForeignKey(KanvasoPosedantoTipo, verbose_name=_('Tipo'), default=None,
                             blank=True, null=True,
                             related_name='%(app_label)s_%(class)s_tipo',
                             on_delete=models.CASCADE)

    # статус владельца холста
    statuso = models.ForeignKey(KanvasoPosedantoStatuso, verbose_name=_('Statuso'), default=None,
                                blank=True, null=True,
                                related_name='%(app_label)s_%(class)s_statuso',
                                on_delete=models.CASCADE)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'kanvasoj_kanvaso_posedantoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Posedanto de kanvaso de kanvasoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Posedantoj de kanvaso de kanvasoj')
        # права
        permissions = (
            ('povas_vidi_kanvasoj_kanvaso_posedantoj', _('Povas vidi posedantoj de kanvaso de kanvasoj')),
            ('povas_krei_kanvasoj_kanvaso_posedantoj', _('Povas krei posedantoj de kanvaso de kanvasoj')),
            ('povas_forigi_kanvasoj_kanvaso_posedantoj', _('Povas forigi posedantoj de kanvaso de kanvasoj')),
            ('povas_shangxi_kanvasoj_kanvaso_posedantoj', _('Povas ŝanĝi posedantoj de kanvaso de kanvasoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле kanvaso этой модели
        return '{}'.format(self.kanvaso)

    # реализация автоинкремента шаблона при сохранении
    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):

        if self.sxablono_sistema:
            if self.sxablono_sistema_id is None or not self.sxablono_sistema_id:
                model = getattr(sys.modules[self.__module__], self.__class__.__name__)
                next_id = model.objects.all().aggregate(Max('sxablono_sistema_id'))['sxablono_sistema_id__max']

                if next_id is None:
                    next_id = 1
                else:
                    next_id = next_id + 1
                super(model, self).__setattr__('sxablono_sistema_id', next_id)

        super(KanvasoPosedanto, self).save(force_insert=force_insert, force_update=force_update,
                                                    using=using, update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            if user_obj.is_superuser:
                all_perms = Permission.objects.filter(content_type__app_label='kanvasoj')
            else:
                # выбрать права, какие относятся к моделе
                model_perms = set([
                    'povas_vidi_kanvasoj_kanvaso_posedantoj',
                    'povas_krei_kanvasoj_kanvaso_posedantoj',
                    'povas_forigi_kanvasoj_kanvaso_posedantoj',
                    'povas_shangxi_kanvasoj_kanvaso_posedantoj'
                ])
                # выбираем права, какие есть у пользователя по данной моделе
                all_perms = set(user_obj.user_permissions.filter(
                    content_type__app_label='kanvasoj', codename__in=model_perms).values_list('codename', flat=True))
                # ЗДЕСЬ начинается блок добавления прав согласно условиям пользователя !!!
                # владелец пространства имеет все права

                count_posedantoj = KanvasoPosedanto.objects.filter(posedanto_organizo__organizomembro__uzanto__id=user_obj).count()
                count_posedantoj += KanvasoPosedanto.objects.filter(kanvasoj_kanvasoposedanto_kanvaso__posedanto_komunumo__komunumoj_komunumomembro_posedanto__autoro__id=user_obj).count()

                if (count_posedantoj or (self.posedanto_uzanto==user_obj)):
                    all_perms = all_perms.union({
                        'povas_vidi_kanvasoj_kanvaso_posedantoj',
                        'povas_krei_kanvasoj_kanvaso_posedantoj',
                        'povas_forigi_kanvasoj_kanvaso_posedantoj',
                        'povas_shangxi_kanvasoj_kanvaso_posedantoj',
                    })

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='kanvasoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_posedantoj')
                    or user_obj.has_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_posedantoj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если член организации-владельца (клиента), то выдаём по нему данные
                cond = Q(posedanto_uzanto__id=user_obj.id) | Q(
                    posedanto_organizo__organizomembro__uzanto__id=user_obj.id) | Q(
                    posedanto_komunumo__komunumoj_komunumomembro_posedanto__autoro__id=user_obj.id)
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                # cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_posedantoj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Типы связей холстов между собой, использует абстрактный класс UniversoBazaMaks
class KanvasoLigiloTipo(UniversoBazaMaks):

    # ID записи
    id = models.IntegerField(_('ID'), unique=True, default=0)

    # автор (пользователь, который создал сущность или для которого создана сущность)
    autoro = models.ForeignKey(Uzanto, verbose_name=_('Aŭtoro'), blank=False, default=None,
                               related_name='%(app_label)s_%(class)s_autoro',
                               on_delete=models.CASCADE)

    # название, многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'kanvasoj_kanvaso_ligiloj_tipoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Tipo de ligiloj de kanvaso de kanvasoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Tipoj de ligiloj de kanvaso de kanvasoj')
        # права
        permissions = (
            ('povas_vidi_kanvasoj_kanvaso_ligiloj_tipoj',
             _('Povas vidi tipoj de ligiloj de kanvaso de kanvasoj')),
            ('povas_krei_kanvasoj_kanvaso_ligiloj_tipoj',
             _('Povas krei tipoj de ligiloj de kanvaso de kanvasoj')),
            ('povas_forigi_kanvasoj_kanvaso_ligiloj_tipoj',
             _('Povas forigi tipoj de ligiloj de kanvaso de kanvasoj')),
            ('povas_sxangxi_kanvasoj_kanvaso_ligiloj_tipoj',
             _('Povas ŝanĝi tipoj de ligiloj de kanvaso de kanvasoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}) {}'.format(self.id, get_enhavo(self.nomo, empty_values=True)[0])

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):

        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.all().aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id = next_id + 1
            super(model, self).__setattr__('id', next_id)

        super(KanvasoLigiloTipo, self).save(force_insert=force_insert, force_update=force_update,
                                                     using=using, update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистрированных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('kanvasoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'kanvasoj.povas_vidi_kanvasoj_kanvaso_ligiloj_tipoj',
                'kanvasoj.povas_krei_kanvasoj_kanvaso_ligiloj_tipoj',
                'kanvasoj.povas_forigi_kanvasoj_kanvaso_ligiloj_tipoj',
                'kanvasoj.povas_sxangxi_kanvasoj_kanvaso_ligiloj_tipoj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='kanvasoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_ligiloj_tipoj')
                    or user_obj.has_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_ligiloj_tipoj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_ligiloj_tipoj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Связь холстов между собой, использует абстрактный класс UniversoBazaMaks
class KanvasoLigilo(UniversoBazaMaks):

    # холст владелец связи
    posedanto = models.ForeignKey(Kanvaso, verbose_name=_('Kanvaso - posedanto'),
                                  related_name='%(app_label)s_%(class)s_posedanto',
                                  blank=False, null=False, default=None, on_delete=models.CASCADE)

    # связываемый холст
    ligilo = models.ForeignKey(Kanvaso, verbose_name=_('Kanvaso - ligilo'), blank=False,
                               null=False, default=None, related_name='%(app_label)s_%(class)s_ligilo',
                               on_delete=models.CASCADE)

    # тип связи холстов
    tipo = models.ForeignKey(KanvasoLigiloTipo, verbose_name=_('Tipo'), blank=False, default=None,
                             related_name='%(app_label)s_%(class)s_tipo',
                             on_delete=models.CASCADE)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'kanvasoj_kanvaso_ligiloj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Ligilo de kanvaso de kanvasoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Ligiloj de kanvaso de kanvasoj')
        # права
        permissions = (
            ('povas_vidi_kanvasoj_kanvaso_ligiloj', _('Povas vidi ligiloj de kanvaso de kanvasoj')),
            ('povas_krei_kanvasoj_kanvaso_ligiloj', _('Povas krei ligiloj de kanvaso de kanvasoj')),
            ('povas_forigi_kanvasoj_kanvaso_ligiloj', _('Povas forigi ligiloj de kanvaso de kanvasoj')),
            ('povas_sxangxi_kanvasoj_kanvaso_ligiloj', _('Povas ŝanĝi ligiloj de kanvaso de kanvasoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле uuid этой модели
        return '{}'.format(self.uuid)

    # реализация автоинкремента шаблона при сохранении
    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):

        if self.sxablono_sistema:
            if self.sxablono_sistema_id is None or not self.sxablono_sistema_id:
                model = getattr(sys.modules[self.__module__], self.__class__.__name__)
                next_id = model.objects.all().aggregate(Max('sxablono_sistema_id'))['sxablono_sistema_id__max']

                if next_id is None:
                    next_id = 1
                else:
                    next_id = next_id + 1
                super(model, self).__setattr__('sxablono_sistema_id', next_id)

        super(KanvasoLigilo, self).save(force_insert=force_insert, force_update=force_update,
                                                 using=using, update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистрированных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('kanvasoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'kanvasoj.povas_vidi_kanvasoj_kanvaso_ligiloj',
                'kanvasoj.povas_krei_kanvasoj_kanvaso_ligiloj',
                'kanvasoj.povas_forigi_kanvasoj_kanvaso_ligiloj',
                'kanvasoj.povas_sxangxi_kanvasoj_kanvaso_ligiloj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='kanvasoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_ligiloj')
                    or user_obj.has_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_ligiloj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_ligiloj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Категории объектов холстов, использует абстрактный класс UniversoBazaMaks
class KanvasoObjektoKategorio(UniversoBazaMaks):

    # ID записи для вывода
    id = models.IntegerField(_('ID'), unique=True, default=0)

    # автор (пользователь, который создал сущность)
    autoro = models.ForeignKey(Uzanto, verbose_name=_('Aŭtoro'), blank=False, default=None,
                               related_name='%(app_label)s_%(class)s_autoro',
                               on_delete=models.CASCADE)

    # название, многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # параллельный мир в котором есть эта сущность, может быть в нескольких
    realeco = models.ManyToManyField(Realeco, verbose_name=_('Realeco'),
                                     db_table='kanvasoj_kanvaso_objektoj_kategorioj_realeco_ligiloj')

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'kanvasoj_kanvaso_objektoj_kategorioj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Kategorio de kanvaso objekto de kanvasoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Kategorioj de kanvaso objekto de kanvasoj')
        # права
        permissions = (
            ('povas_vidi_kanvasoj_kanvaso_objekto_kategorioj', _('Povas vidi kategorioj de kanvaso objekto de kanvasoj')),
            ('povas_krei_kanvasoj_kanvaso_objekto_kategorioj', _('Povas krei kategorioj de kanvaso objekto de kanvasoj')),
            ('povas_forigi_kanvasoj_kanvaso_objekto_kategorioj', _('Povas forigi kategorioj de kanvaso objekto de kanvasoj')),
            ('povas_shangxi_kanvasoj_kanvaso_objekto_kategorioj', _('Povas ŝanĝi kategorioj de kanvaso objekto de kanvasoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}) {}'.format(self.id, get_enhavo(self.nomo, empty_values=True)[0])

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):
        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.all().aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id += 1
            super(model, self).__setattr__('id', next_id)

        super(KanvasoObjektoKategorio, self).save(force_insert=force_insert, force_update=force_update,
                                                 using=using, update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистрированных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('kanvasoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_kategorioj',
                'kanvasoj.povas_krei_kanvasoj_kanvaso_objekto_kategorioj',
                'kanvasoj.povas_forigi_kanvasoj_kanvaso_objekto_kategorioj',
                'kanvasoj.povas_shangxi_kanvasoj_kanvaso_objekto_kategorioj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='kanvasoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_kategorioj')
                    or user_obj.has_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_kategorioj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_kategorioj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Типы объектов холстов, использует абстрактный класс UniversoBazaMaks
class KanvasoObjektoTipo(UniversoBazaMaks):

    # ID записи для вывода
    id = models.IntegerField(_('ID'), unique=True, default=0)

    # автор (пользователь, который создал сущность)
    autoro = models.ForeignKey(Uzanto, verbose_name=_('Aŭtoro'), blank=False, default=None,
                               related_name='%(app_label)s_%(class)s_autoro',
                               on_delete=models.CASCADE)

    # название, многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # параллельный мир в котором есть эта сущность, может быть в нескольких
    realeco = models.ManyToManyField(Realeco, verbose_name=_('Realeco'), blank=True,
                                     db_table='kanvasoj_kanvaso_objekto_tipoj_realeco_ligiloj')

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'kanvasoj_kanvaso_objekto_tipoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Tipo de kanvaso objekto de kanvasoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Tipoj de kanvaso objekto de kanvasoj')
        # права
        permissions = (
            ('povas_vidi_kanvasoj_kanvaso_objekto_tipoj', _('Povas vidi tipoj de kanvaso objekto de kanvasoj')),
            ('povas_krei_kanvasoj_kanvaso_objekto_tipoj', _('Povas krei tipoj de kanvaso objekto de kanvasoj')),
            ('povas_forigi_kanvasoj_kanvaso_objekto_tipoj', _('Povas forigi tipoj de kanvaso objekto de kanvasoj')),
            ('povas_shangxi_kanvasoj_kanvaso_objekto_tipoj', _('Povas ŝanĝi tipoj de kanvaso objekto de kanvasoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}) {}'.format(self.id, get_enhavo(self.nomo, empty_values=True)[0])

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):
        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.all().aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id += 1
            super(model, self).__setattr__('id', next_id)

        super(KanvasoObjektoTipo, self).save(force_insert=force_insert, force_update=force_update,
                                            using=using, update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистрированных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('kanvasoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_tipoj',
                'kanvasoj.povas_krei_kanvasoj_kanvaso_objekto_tipoj',
                'kanvasoj.povas_forigi_kanvasoj_kanvaso_objekto_tipoj',
                'kanvasoj.povas_shangxi_kanvasoj_kanvaso_objekto_tipoj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='kanvasoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_tipoj')
                    or user_obj.has_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_tipoj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_tipoj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Статус объектов холстов, использует абстрактный класс UniversoBazaMaks
class KanvasoObjektoStatuso(UniversoBazaMaks):

    # уникальный личный ID
    id = models.IntegerField(_('ID'), unique=True, default=0)

    # автор (пользователь, который создал сущность)
    autoro = models.ForeignKey(Uzanto, verbose_name=_('Aŭtoro'), blank=False, default=None,
                               related_name='%(app_label)s_%(class)s_autoro',
                               on_delete=models.CASCADE)

    # название, многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                 encoder=CallableEncoder)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'kanvasoj_kanvaso_objekto_statusoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Statuso de kanvaso objekto de kanvasoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Statusoj de kanvaso objekto de kanvasoj')
        # права
        permissions = (
            ('povas_vidi_kanvasoj_kanvaso_objekto_statusoj', _('Povas vidi statusoj de kanvaso objekto de kanvasoj')),
            ('povas_krei_kanvasoj_kanvaso_objekto_statusoj', _('Povas krei statusoj de kanvaso objekto de kanvasoj')),
            ('povas_forigi_kanvasoj_kanvaso_objekto_statusoj', _('Povas forigi statusoj de kanvaso objekto de kanvasoj')),
            ('povas_shangxi_kanvasoj_kanvaso_objekto_statusoj', _('Povas ŝanĝi statusoj de kanvaso objekto de kanvasoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}) {}'.format(self.id, get_enhavo(self.nomo, empty_values=True)[0])

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):

        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.all().aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id = next_id + 1
            super(model, self).__setattr__('id', next_id)

        super(KanvasoObjektoStatuso, self).save(force_insert=force_insert, force_update=force_update,
                                               using=using, update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистрированных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('kanvasoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_statusoj',
                'kanvasoj.povas_krei_kanvasoj_kanvaso_objekto_statusoj',
                'kanvasoj.povas_forigi_kanvasoj_kanvaso_objekto_statusoj',
                'kanvasoj.povas_shangxi_kanvasoj_kanvaso_objekto_statusoj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='kanvasoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_statusoj')
                    or user_obj.has_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_statusoj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_statusoj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Объекты холстов, использует абстрактный класс UniversoBazaRealeco
class KanvasoObjekto(UniversoBazaRealeco):

    # холст в который входит объект холста
    kanvaso = models.ForeignKey(Kanvaso, verbose_name=_('Kanvaso'), blank=False, default=None,
                              related_name='%(app_label)s_%(class)s_kanvaso',
                              on_delete=models.CASCADE)

    # уникальный ID в разрезе холста
    id = models.IntegerField(_('ID'), db_index=True, null=True, default=0)

    # категория объектов холстов
    kategorio = models.ManyToManyField(KanvasoObjektoKategorio, verbose_name=_('Kategorio'),
                                       blank=True,
                                       db_table='kanvasoj_kanvaso_objekto_kategorioj_ligiloj')

    # тип объектов холстов
    tipo = models.ForeignKey(KanvasoObjektoTipo, verbose_name=_('Tipo'), blank=False, default=None,
                             related_name='%(app_label)s_%(class)s_tipo',
                             on_delete=models.CASCADE)

    # статус объектов холстов
    statuso = models.ForeignKey(KanvasoObjektoStatuso, verbose_name=_('Statuso'), default=None,
                                blank=True, null=True,
                                related_name='%(app_label)s_%(class)s_statuso',
                                on_delete=models.CASCADE)

    # позиция в списке
    pozicio = models.IntegerField(_('Pozicio'), blank=True, null=True, default=None)

    # Координаты X
    koordinato_x = models.IntegerField(_('Координаты X'), blank=True, null=True, default=None)

    # Координаты Y
    koordinato_y = models.IntegerField(_('Координаты Y'), blank=True, null=True, default=None)

    # Ширина
    largxo = models.IntegerField(_('Ширина'), blank=True, null=True, default=None)

    # Длина
    longo = models.IntegerField(_('Длина'), blank=True, null=True, default=None)

    # название, многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'kanvasoj_kanvaso_objekto'
        # читабельное название модели, в единственном числе
        verbose_name = _('Kanvaso objekto')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Kanvasoj objektoj')
        # уникальность
        unique_together = ("id","kanvaso")
        # права
        permissions = (
            ('povas_vidi_kanvasoj_kanvaso_objekto', _('Povas vidi kanvaso objekto de kanvasoj')),
            ('povas_krei_kanvasoj_kanvaso_objekto', _('Povas krei kanvaso objekto de kanvasoj')),
            ('povas_forigi_kanvasoj_kanvaso_objekto', _('Povas forigi kanvaso objekto de kanvasoj')),
            ('povas_shangxi_kanvasoj_kanvaso_objekto', _('Povas ŝanĝi kanvaso objekto de kanvasoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}) {}'.format(self.id, get_enhavo(self.nomo, empty_values=True)[0])

    # реализация автоинкремента шаблона при сохранении
    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):

        if self.sxablono_sistema:
            if self.sxablono_sistema_id is None or not self.sxablono_sistema_id:
                model = getattr(sys.modules[self.__module__], self.__class__.__name__)
                next_id = model.objects.all().aggregate(Max('sxablono_sistema_id'))['sxablono_sistema_id__max']

                if next_id is None:
                    next_id = 1
                else:
                    next_id = next_id + 1
                super(model, self).__setattr__('sxablono_sistema_id', next_id)

        # реализация автоинкремента при сохранении
        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.filter(kanvaso=self.kanvaso).aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id = next_id + 1
            super(model, self).__setattr__('id', next_id)

        super(KanvasoObjekto, self).save(force_insert=force_insert, force_update=force_update,
                                    using=using, update_fields=update_fields)


    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистрированных для приложения
            if user_obj.is_superuser:
                all_perms = Permission.objects.filter(content_type__app_label='kanvasoj')
            else:
                # выбрать права, какие относятся к моделе
                model_perms = set([
                    'povas_vidi_kanvasoj_kanvaso_objekto',
                    'povas_krei_kanvasoj_kanvaso_objekto',
                    'povas_forigi_kanvasoj_kanvaso_objekto',
                    'povas_shangxi_kanvasoj_kanvaso_objekto'
                ])
                # выбираем права, какие есть у пользователя по данной моделе
                all_perms = set(user_obj.user_permissions.filter(
                    content_type__app_label='kanvasoj', codename__in=model_perms).values_list('codename', flat=True))
                # ЗДЕСЬ начинается блок добавления прав согласно условиям пользователя !!!
                # владелец объектов холстов имеет все права
                count_posedantoj = KanvasoObjektoPosedanto.objects.filter(kanvaso_objekto=self, posedanto_uzanto=user_obj).count()
                if count_posedantoj:
                    all_perms = all_perms.union({
                        'povas_vidi_kanvasoj_kanvaso_objekto',
                        'povas_krei_kanvasoj_kanvaso_objekto',
                        'povas_forigi_kanvasoj_kanvaso_objekto',
                        'povas_shangxi_kanvasoj_kanvaso_objekto',
                        'povas_vidi_kanvasoj_kanvaso_objekto_posedantoj',
                        'povas_krei_kanvasoj_kanvaso_objekto_posedantoj', # имеет право создавать владельцев
                    })
                # владелец холста имеет полные права 
                count_posedantoj =  KanvasoPosedanto.objects.filter(kanvaso=self.kanvaso, posedanto_uzanto=user_obj).count()
                if count_posedantoj:
                    all_perms = all_perms.union({
                        'povas_vidi_kanvasoj_kanvaso_objekto',
                        'povas_krei_kanvasoj_kanvaso_objekto',
                        'povas_forigi_kanvasoj_kanvaso_objekto',
                        'povas_shangxi_kanvasoj_kanvaso_objekto',
                        'povas_vidi_kanvasoj_kanvaso_objekto_posedantoj',
                        'povas_krei_kanvasoj_kanvaso_objekto_posedantoj', # имеет право создавать владельцев
                    })

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='kanvasoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto')
                    or user_obj.has_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                # cond = Q(uuid__isnull=True)
                cond = Q(kanvaso__kanvasoj_kanvasoposedanto_kanvaso__posedanto_uzanto__id=user_obj.id) | Q(
                    kanvaso__kanvasoj_kanvasoposedanto_kanvaso__posedanto_organizo__organizomembro__uzanto__id=user_obj.id) | Q(
                    kanvaso__kanvasoj_kanvasoposedanto_kanvaso__posedanto_komunumo__komunumoj_komunumomembro_posedanto__autoro__id=user_obj.id) | Q(
                    kanvasoj_kanvasoobjektoposedanto_kanvaso_objekto__posedanto_uzanto__id=user_obj.id) | Q(
                    kanvasoj_kanvasoobjektoposedanto_kanvaso_objekto__posedanto_organizo__organizomembro__uzanto__id=user_obj.id)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Типы владельцев объектов холстов, использует абстрактный класс UniversoBazaMaks
class KanvasoObjektoPosedantoTipo(UniversoBazaMaks):

    # уникальный личный ID
    id = models.IntegerField(_('ID'), unique=True, default=0)

    # автор (пользователь, который создал сущность)
    autoro = models.ForeignKey(Uzanto, verbose_name=_('Aŭtoro'), blank=False, default=None,
                               related_name='%(app_label)s_%(class)s_autoro',
                               on_delete=models.CASCADE)

    # название, многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'kanvasoj_kanvaso_objekto_posedantoj_tipoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Tipo de posedantoj de kanvaso objekto de kanvasoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Tipoj de posedantoj de kanvaso objekto de kanvasoj')
        # права
        permissions = (
            ('povas_vidi_kanvasoj_kanvaso_objekto_posedantoj_tipoj', _('Povas vidi tipoj de posedantoj de kanvaso objekto de kanvasoj')),
            ('povas_krei_kanvasoj_kanvaso_objekto_posedantoj_tipoj', _('Povas krei tipoj de posedantoj de kanvaso objekto de kanvasoj')),
            ('povas_forigi_kanvasoj_kanvaso_objekto_posedantoj_tipoj', _('Povas forigi tipoj de posedantoj de kanvaso objekto de kanvasoj')),
            ('povas_shangxi_kanvasoj_kanvaso_objekto_posedantoj_tipoj', _('Povas ŝanĝi tipoj de posedantoj de kanvaso objekto de kanvasoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}) {}'.format(self.id, get_enhavo(self.nomo, empty_values=True)[0])

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):

        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.all().aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id = next_id + 1
            super(model, self).__setattr__('id', next_id)

        super(KanvasoObjektoPosedantoTipo, self).save(force_insert=force_insert, force_update=force_update,
                                                     using=using, update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистрированных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('kanvasoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_posedantoj_tipoj',
                'kanvasoj.povas_krei_kanvasoj_kanvaso_objekto_posedantoj_tipoj',
                'kanvasoj.povas_forigi_kanvasoj_kanvaso_objekto_posedantoj_tipoj',
                'kanvasoj.povas_shangxi_kanvasoj_kanvaso_objekto_posedantoj_tipoj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='kanvasoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_posedantoj_tipoj')
                    or user_obj.has_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_posedantoj_tipoj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_posedantoj_tipoj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Статус владельца объектов холстов, использует абстрактный класс UniversoBazaMaks
class KanvasoObjektoPosedantoStatuso(UniversoBazaMaks):

    # уникальный личный ID
    id = models.IntegerField(_('ID'), unique=True, default=0)

    # автор (пользователь, который создал сущность)
    autoro = models.ForeignKey(Uzanto, verbose_name=_('Aŭtoro'), blank=False, default=None,
                               related_name='%(app_label)s_%(class)s_autoro',
                               on_delete=models.CASCADE)

    # название, многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'kanvasoj_kanvaso_objekto_posedantoj_statusoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Statuso de posedantoj de kanvaso objekto de kanvasoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Statusoj de posedantoj de kanvaso objekto de kanvasoj')
        # права
        permissions = (
            ('povas_vidi_kanvasoj_kanvaso_objekto_posedantoj_statusoj',
             _('Povas vidi statusoj de posedantoj de kanvaso objekto de kanvasoj')),
            ('povas_krei_kanvasoj_kanvaso_objekto_posedantoj_statusoj',
             _('Povas krei statusoj de posedantoj de kanvaso objekto de kanvasoj')),
            ('povas_forigi_kanvasoj_kanvaso_objekto_posedantoj_statusoj',
             _('Povas forigi statusoj de posedantoj de kanvaso objekto de kanvasoj')),
            ('povas_shangxi_kanvasoj_kanvaso_objekto_posedantoj_statusoj',
             _('Povas ŝanĝi statusoj de posedantoj de kanvaso objekto de kanvasoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}) {}'.format(self.id, get_enhavo(self.nomo, empty_values=True)[0])

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):

        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.all().aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id = next_id + 1
            super(model, self).__setattr__('id', next_id)

        super(KanvasoObjektoPosedantoStatuso, self).save(force_insert=force_insert, force_update=force_update,
                                                        using=using, update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистрированных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('kanvasoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_posedantoj_statusoj',
                'kanvasoj.povas_krei_kanvasoj_kanvaso_objekto_posedantoj_statusoj',
                'kanvasoj.povas_forigi_kanvasoj_kanvaso_objekto_posedantoj_statusoj',
                'kanvasoj.povas_shangxi_kanvasoj_kanvaso_objekto_posedantoj_statusoj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='kanvasoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_posedantoj_statusoj')
                    or user_obj.has_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_posedantoj_statusoj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_posedantoj_statusoj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Владельцы объектов холстов, использует абстрактный класс UniversoBazaRealeco
class KanvasoObjektoPosedanto(UniversoBazaRealeco):

    # объект холста
    kanvaso_objekto = models.ForeignKey(KanvasoObjekto, verbose_name=_('Tasko'), blank=False, null=False,
                              related_name='%(app_label)s_%(class)s_kanvaso_objekto',
                              default=None, on_delete=models.CASCADE)

    # пользователь владелец объекта холста
    posedanto_uzanto = models.ForeignKey(Uzanto, verbose_name=_('Posedanta uzanto'), blank=True, null=True,
                                         related_name='%(app_label)s_%(class)s_posedanto_uzanto',
                                         default=None, on_delete=models.CASCADE)

    # организация владелец объекта холста
    posedanto_organizo = models.ForeignKey(Organizo, verbose_name=_('Posedanta organizo'), blank=True,
                                           related_name='%(app_label)s_%(class)s_posedanto_organizo',
                                           null=True, default=None, on_delete=models.CASCADE)

    # тип владельца объекта холста
    tipo = models.ForeignKey(KanvasoObjektoPosedantoTipo, verbose_name=_('Tipo'), blank=False, default=None,
                             related_name='%(app_label)s_%(class)s_tipo',
                             on_delete=models.CASCADE)
    
    # статус владельца объекта холста
    statuso = models.ForeignKey(KanvasoObjektoPosedantoStatuso, verbose_name=_('Statuso'), blank=False, default=None,
                                related_name='%(app_label)s_%(class)s_statuso',
                                on_delete=models.CASCADE)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'kanvasoj_kanvaso_objekto_posedantoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Posedanto de kanvaso objekto de kanvasoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Posedantoj de kanvaso objektoj de kanvasoj')
        # права
        permissions = (
            ('povas_vidi_kanvasoj_kanvaso_objekto_posedantoj', _('Povas vidi posedantoj de kanvaso objekto de kanvasoj')),
            ('povas_krei_kanvasoj_kanvaso_objekto_posedantoj', _('Povas krei posedantoj de kanvaso objekto de kanvasoj')),
            ('povas_forigi_kanvasoj_kanvaso_objekto_posedantoj', _('Povas forigi posedantoj de kanvaso objekto de kanvasoj')),
            ('povas_shangxi_kanvasoj_kanvaso_objekto_posedantoj', _('Povas ŝanĝi posedantoj de kanvaso objekto de kanvasoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле kanvaso_objekto этой модели
        return '{}'.format(self.kanvaso_objekto)

    # реализация автоинкремента шаблона при сохранении
    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):

        if self.sxablono_sistema:
            if self.sxablono_sistema_id is None or not self.sxablono_sistema_id:
                model = getattr(sys.modules[self.__module__], self.__class__.__name__)
                next_id = model.objects.all().aggregate(Max('sxablono_sistema_id'))['sxablono_sistema_id__max']

                if next_id is None:
                    next_id = 1
                else:
                    next_id = next_id + 1
                super(model, self).__setattr__('sxablono_sistema_id', next_id)

        super(KanvasoObjektoPosedanto, self).save(force_insert=force_insert, force_update=force_update,
                                             using=using, update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистрированных для приложения
            if user_obj.is_superuser:
                all_perms = Permission.objects.filter(content_type__app_label='kanvasoj')
            else:
                # выбрать права, какие относятся к моделе
                model_perms = set([
                    'povas_vidi_kanvasoj_kanvaso_objekto_posedantoj',
                    'povas_krei_kanvasoj_kanvaso_objekto_posedantoj',
                    'povas_forigi_kanvasoj_kanvaso_objekto_posedantoj',
                    'povas_shangxi_kanvasoj_kanvaso_objekto_posedantoj'
                ])
                # выбираем права, какие есть у пользователя по данной моделе
                all_perms = set(user_obj.user_permissions.filter(
                    content_type__app_label='kanvasoj', codename__in=model_perms).values_list('codename', flat=True))
                # ЗДЕСЬ начинается блок добавления прав согласно условиям пользователя !!!
                # владелец пространства имеет все права
                count_posedantoj = KanvasoObjektoPosedanto.objects.filter(posedanto_organizo__organizomembro__uzanto__id=user_obj).count()
                if (count_posedantoj or (self.posedanto_uzanto==user_obj)):
                    all_perms = all_perms.union({
                        'povas_vidi_kanvasoj_kanvaso_objekto_posedantoj',
                        'povas_krei_kanvasoj_kanvaso_objekto_posedantoj',
                        'povas_forigi_kanvasoj_kanvaso_objekto_posedantoj',
                        'povas_shangxi_kanvasoj_kanvaso_objekto_posedantoj',
                    })

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='kanvasoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_posedantoj')
                    or user_obj.has_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_posedantoj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                cond = Q(posedanto_uzanto__id=user_obj.id) | Q(
                    posedanto_organizo__organizomembro__uzanto__id=user_obj.id)
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                # cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_posedantoj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Типы связей объектов холстов между собой, использует абстрактный класс UniversoBazaMaks
class KanvasoObjektoLigiloTipo(UniversoBazaMaks):

    # ID записи
    id = models.IntegerField(_('ID'), unique=True, default=0)

    # автор (пользователь, который создал сущность или для которого создана сущность)
    autoro = models.ForeignKey(Uzanto, verbose_name=_('Aŭtoro'), blank=False, default=None,
                               related_name='%(app_label)s_%(class)s_autoro',
                               on_delete=models.CASCADE)

    # название, многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'kanvasoj_kanvaso_objekto_ligiloj_tipoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Tipo de ligiloj de kanvaso objekto de kanvasoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Tipoj de ligiloj de kanvaso objekto de kanvasoj')
        # права
        permissions = (
            ('povas_vidi_kanvasoj_kanvaso_objekto_ligiloj_tipoj',
             _('Povas vidi tipoj de ligiloj de kanvaso objekto de kanvasoj')),
            ('povas_krei_kanvasoj_kanvaso_objekto_ligiloj_tipoj',
             _('Povas krei tipoj de ligiloj de kanvaso objekto de kanvasoj')),
            ('povas_forigi_kanvasoj_kanvaso_objekto_ligiloj_tipoj',
             _('Povas forigi tipoj de ligiloj de kanvaso objekto de kanvasoj')),
            ('povas_sxangxi_kanvasoj_kanvaso_objekto_ligiloj_tipoj',
             _('Povas ŝanĝi tipoj de ligiloj de kanvaso objekto de kanvasoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}) {}'.format(self.id, get_enhavo(self.nomo, empty_values=True)[0])

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):

        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.all().aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id = next_id + 1
            super(model, self).__setattr__('id', next_id)

        super(KanvasoObjektoLigiloTipo, self).save(force_insert=force_insert, force_update=force_update,
                                              using=using, update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистрированных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('kanvasoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_ligiloj_tipoj',
                'kanvasoj.povas_krei_kanvasoj_kanvaso_objekto_ligiloj_tipoj',
                'kanvasoj.povas_forigi_kanvasoj_kanvaso_objekto_ligiloj_tipoj',
                'kanvasoj.povas_sxangxi_kanvasoj_kanvaso_objekto_ligiloj_tipoj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='kanvasoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_ligiloj_tipoj')
                    or user_obj.has_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_ligiloj_tipoj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_ligiloj_tipoj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Связь объектов холстов между собой, использует абстрактный класс UniversoBazaMaks
class KanvasoObjektoLigilo(UniversoBazaMaks):

    # объект холста владелец связи
    posedanto = models.ForeignKey(KanvasoObjekto, verbose_name=_('Kanvaso objekto posedanto'),
                                  related_name='%(app_label)s_%(class)s_posedanto',
                                  blank=False, null=False, default=None, on_delete=models.CASCADE)

    # связываемый объект холста - убрано, т.к. множественная связь сильно усложнит работу разработчикам
    # ligilo = models.ForeignKey(KanvasoObjekto, verbose_name=_('Tasko - ligilo'), blank=False,
    #                            null=False, default=None, 
    #                            related_name='%(app_label)s_%(class)s_ligilo',
    #                            on_delete=models.CASCADE)

    # связываемый объект холста - должен быть только один, т.к. множественные связи приведут к очень сложным и 
    # запутанным в визуализации связям, что только навредит проекту
    ligilo = models.OneToOneField(KanvasoObjekto, verbose_name=_('Kanvaso objekto ligilo'), blank=False,
                               null=False, default=None, 
                               related_name='%(app_label)s_%(class)s_ligilo',
                               on_delete=models.CASCADE)

    # тип связи шаблонов объектов холстов
    tipo = models.ForeignKey(KanvasoObjektoLigiloTipo, verbose_name=_('Tipo'), blank=False, default=None,
                             related_name='%(app_label)s_%(class)s_tipo',
                             on_delete=models.CASCADE)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'kanvasoj_kanvaso_objekto_ligiloj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Ligilo de kanvaso objekto de kanvasoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Ligiloj de kanvaso objekto de kanvasoj')
        # права
        permissions = (
            ('povas_vidi_kanvasoj_kanvaso_objekto_ligiloj', _('Povas vidi ligiloj de kanvaso objekto de kanvasoj')),
            ('povas_krei_kanvasoj_kanvaso_objekto_ligiloj', _('Povas krei ligiloj de kanvaso objekto de kanvasoj')),
            ('povas_forigi_kanvasoj_kanvaso_objekto_ligiloj', _('Povas forigi ligiloj de kanvaso objekto de kanvasoj')),
            ('povas_sxangxi_kanvasoj_kanvaso_objekto_ligiloj', _('Povas ŝanĝi ligiloj de kanvaso objekto de kanvasoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле uuid этой модели
        return '{}'.format(self.uuid)

    # реализация автоинкремента шаблона при сохранении
    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):

        if self.sxablono_sistema:
            if self.sxablono_sistema_id is None or not self.sxablono_sistema_id:
                model = getattr(sys.modules[self.__module__], self.__class__.__name__)
                next_id = model.objects.all().aggregate(Max('sxablono_sistema_id'))['sxablono_sistema_id__max']

                if next_id is None:
                    next_id = 1
                else:
                    next_id = next_id + 1
                super(model, self).__setattr__('sxablono_sistema_id', next_id)

        super(KanvasoObjektoLigilo, self).save(force_insert=force_insert, force_update=force_update,
                                              using=using, update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистрированных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('kanvasoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_ligiloj',
                'kanvasoj.povas_krei_kanvasoj_kanvaso_objekto_ligiloj',
                'kanvasoj.povas_forigi_kanvasoj_kanvaso_objekto_ligiloj',
                'kanvasoj.povas_sxangxi_kanvasoj_kanvaso_objekto_ligiloj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='kanvasoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_ligiloj')
                    or user_obj.has_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_ligiloj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('kanvasoj.povas_vidi_kanvasoj_kanvaso_objekto_ligiloj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond
